package com.vert.db.model;




import com.vert.db.SqlBuilder;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Classname DBModel
 * @Description TODO
 * @Date 2022/5/29 20:18
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class DBModel {

  /**
   * 表名
   */
  private String tableName;
  /**
   * 主键id
   */
  private String id;
  /**
   * 属性(左边属性)
   */
  private HashMap<String,String> fields;
  /**
   * 反射类
   */
  private Class<?> cls;

  public <T> Object getObject(){
      try {
          return this.cls.newInstance();
      }catch (Exception e){
        e.printStackTrace();
      }
      return null;
  }

  public Field[] getFieldList(){
    return this.cls.getDeclaredFields();
  }

  public Field getFieldByFieldName(String fieldName){
      Field[] fields=this.getFieldList();
      for (int i = 0; i < fields.length ; i++) {
          Field field = fields[i];
          if(fieldName.equals(field.getName())){
            return field;
          }
      }
      return null;
  }

  public SqlBuilder getSqlBuilder() {
      SqlBuilder sqlBuilder = new SqlBuilder();
      String tableName=this.getTableName();
      HashMap<String,String> fields=this.fields;
      List<String> strings=new ArrayList<>();
      strings.add(this.id);
      for (Map.Entry<String,String> obj : fields.entrySet()){
          Object dBField=obj.getValue();
          strings.add(String.valueOf(dBField.toString()));
      }
      sqlBuilder.select(strings);
      sqlBuilder.from(tableName);
      return sqlBuilder;
  }

  public String getSelectAllList(){
      StringBuilder stringBuilder=this.getSelectDdFieldCommon();
      return stringBuilder.toString();
  }

  public Object getValueByFieldName(Object obj,String fieldName)  {
        Field field = this.getFieldByFieldName(fieldName);
        field.setAccessible(true);
        try {
          return field.get(obj);
        }catch (IllegalAccessException e){
          e.printStackTrace();
        }
        return null;
  }

  public void setFieldValueByDBField(Object obj,Object value,String dbField){
      Field field=this.getFieldByDBField(dbField);
      field.setAccessible(true);
      try {
          field.set(obj,value);
      }catch (IllegalAccessException e) {
          e.printStackTrace();
      }
  }

//  public int getInt(Object obj){
//      String s=String.valueOf(obj);
//      return Integer.parseInt(s);
//  }

  public Field getFieldByDBField(String dbField){
      HashMap<String, String> hashMap=this.fields;
      for (Map.Entry<String,String> obj : hashMap.entrySet()){
          String fieldName = obj.getKey();
          String dbFieldValue=obj.getValue();
          if(!dbFieldValue.equals(dbField)){
            continue;
          }
          Field field=this.getFieldByFieldName(fieldName);
          return field;
      }
      return null;
  }

  public void setFieldValue(Object obj,Object value,String fieldName){
      Field field=this.getFieldByFieldName(fieldName);
      field.setAccessible(true);
      try {
        field.set(obj, value);
      }catch (IllegalAccessException e){
        e.printStackTrace();
      }
  }

  public String getByIdSql(Object obj){
      StringBuilder sb=getSelectDdFieldCommon();
      sb.append(" WHERE ").append(this.id).append("='")
        .append(obj).append("'");
      return sb.toString();
  }

  public StringBuilder getSelectDdFieldCommon(){
      StringBuilder sb = new StringBuilder();
      sb.append("SELECT ");
      HashMap<String, String> fieldMaps=this.getFields();
      boolean flag=true;
      for (Map.Entry<String, String> entry : fieldMaps.entrySet()) {
        String fielName=entry.getKey();
        String dbField=entry.getValue();
        if(flag){
            sb.append(dbField);
            flag=false;
        }else {
            sb.append(",").append(dbField);
        }
      }
      sb.append(" FROM ").append(this.tableName);
      return sb;
  }

  public <T> String updateSql(T t){
      String fieldName=this.getFields().get(this.id);
      Object idValue=this.getValueByFieldName(t,fieldName);
      StringBuilder sb=new StringBuilder();
      HashMap<String, String> fieldMaps=this.getFields();
      StringJoiner stringJoiner=new StringJoiner(",");
      for (Map.Entry<String, String> entry : fieldMaps.entrySet()) {
          String fielName=entry.getKey();
          String dbField=entry.getValue();
          Object val=this.getValueByFieldName(t,fielName);
          if(val == null){
              continue;
          }
          stringJoiner.add(dbField+" = '"+val+"'");
      }
      sb.append("UPDATE ").append(this.tableName).append(" set ").append(stringJoiner.toString());
      sb.append(" WHERE ").append(this.id).append("='").append(idValue).append("'");
      String sql=sb.toString();
      return sql;
  }

  public <T> String getSaveSQL(T t){
    String tableName=this.getTableName();
    StringJoiner fields=null;
    fields=new StringJoiner(",","(",")");
    StringJoiner values=null;
    values=new StringJoiner("','","('","')");
    HashMap<String, String> fieldMaps=this.getFields();
    for (Map.Entry<String,String> map: fieldMaps.entrySet()){
      String fielName=map.getKey();
      String dbField=map.getValue();
      Object val=this.getValueByFieldName(t,fielName);
      if(val == null){
        continue;
      }
      if(val instanceof Date){
          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          val=sdf.format(val);
      }
      fields.add(dbField);
      values.add(String.valueOf(val));
    }
    StringBuilder sb = null;
    sb=new StringBuilder();
    sb.append("INSERT INTO ").append(tableName).append(" ").append(fields.toString()).append(" VALUES ").append(values.toString());
    return sb.toString();
  }

  public String getTableName() {
    return tableName;
  }

  public void setTableName(String tableName) {
    this.tableName = tableName;
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  /**
   * k 属性
   * v 注解值
   * @return
   */
  public HashMap<String, String> getFields() {
    return fields;
  }

  public void setFields(HashMap<String, String> fields) {
    this.fields = fields;
  }

  public Class<?> getCls() {
    return cls;
  }

  public void setCls(Class<?> cls) {
    this.cls = cls;
  }

  public DBModel(String tableName, String id, HashMap<String, String> fields, Class<?> cls) {
    this.tableName = tableName;
    this.id = id;
    this.fields = fields;
    this.cls = cls;
  }

  public DBModel() {
  }
}
